package cn.ml.mymvcdemo.main;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.*;

/**
 * 加载并解析 main.xml
 * 根据请求的uri 查找main.xml中配置的action name相同的行为执行
 */

public class MainController extends HttpServlet {
    private ActionMap actionMap=new ActionMap();
    private String confPath = "main.xml";

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //根据请求的uri 查找main.xml中配置的action name相同的行为执行
        //反射
        String uri = req.getRequestURI();
        String actionName = uri.substring(uri.lastIndexOf("/")+1,uri.lastIndexOf(".do"));
        Action action = actionMap.findAction(actionName);
        try {
            Class clazz = Class.forName(action.getClassName());//得到TestAction
            Object obj = clazz.newInstance();
            //Method method = clazz.getDeclaredMethod(action.getMethodName());
            Method [] methods = clazz.getDeclaredMethods();//得到main.xml方法名（say）
            Method method = null;
            for(Method m : methods){
                if(m.getName().equals(action.getMethodName())){
                    method = m;
                }
            }
            Parameter[] parameters = method.getParameters();//获得TestAction中所有方法
            List pvs = new ArrayList();
            Map model = null;
            for(Parameter p:parameters){
                Object value = req.getParameter(p.getName());
                System.out.println(p.getType().getSimpleName());
                if(p.getType().getSimpleName().equals("int")){
                   // value = Integer.parseInt(value.toString());
                    value = Integer.parseInt(value.toString());
                }
                System.out.println(p.getName()+"="+value);
                if(p.getType().getSimpleName().equals("Map")){ //参数类型是Map类型
                    model = new HashMap();
                    value = model;
                }
                pvs.add(value);
            }

            method.invoke(obj,pvs.toArray());
            if (model!=null){
                model.forEach((k,v)->{
                    req.setAttribute(k.toString(),v);
                });
            }
            if("dispatcher".equals(action.getResult().getType())){
                req.getRequestDispatcher(action.getResult().getPath()).forward(req,resp);
            }else {
                resp.sendRedirect(action.getResult().getPath());
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void init() throws ServletException {
        //加载并解析 main.xml
        String conf = getServletConfig().getInitParameter("conf");
        if(conf != null){
            confPath=conf;
        }
        //ActionMap-->(String key,Action value)   Action-->(String name,String className,String methodName,Result result) Result-->(String type,String path)
        parseMain();
    }

    private void parseMain() {

        SAXReader reader = new SAXReader();
        try {
            Document document = reader.read(MainController.class.getClassLoader().getResourceAsStream(confPath));
            Element root = document.getRootElement();
            // iterate through child elements of root
            for (Iterator<Element> it = root.elementIterator(); it.hasNext();) {
                Element element = it.next();
                String actionName = element.attributeValue("name");
                String className = element.attributeValue("class");
                String methodName = element.attributeValue("method");
                String type = element.element("result").attributeValue("type");
                String path = element.elementTextTrim("result");
                Result result = new Result(type,path);
                Action action = new Action(actionName,className,methodName,result);
                actionMap.putAction(actionName,action);
            }

        } catch (DocumentException e) {
            e.printStackTrace();
        }


    }
}
